#include "coin2/base/time.h"
#include "coin2/base/time_window.h"
#include "coin2/exchange/base/executor/live_executor.h"
#include "coin2/exchange/bitmex/feed_v1/subsystem.h"
#include "coin2/exchange/huobi/feed_v1/subsystem.h"
#include "coin2/exchange/huobi/symbology/product.h"
#include "coin2/exchange/huobi_futures/feed_v1/subsystem.h"
#include "coin2/exchange/huobi_futures/symbology/product.h"
#include "coin2/exchange/okex/feed_v3/subsystem.h"
#include "coin2/feed/fastfeed/subsystem.h"

using coin2::base::TimeWindow;
using coin2::exchange::huobi::symbology::HuobiProduct;
using coin2::exchange::huobi_futures::symbology::HuobiFuturesProduct;

class Sampler : public IFeedSubscriber {
 public:
  Sampler(int64_t start, int64_t end, int64_t period = 100'000) : period_(period) {  // 100ms
    // start_ =
    // 1231312 =>
    // 1231400
    /*
        100
                101
                110
                150
                170
        200  <- last sample ts
                210
                250 <- current
                270
        300 <- go to here
        400
                410
                490
    */
    last_sample_ts = ((start - 1) / period_) * period_;
  }
  void onTradeFeed(const FeedUpdate& upd) {
    // auto trade = upd.trade();
  }
  void onBookFeed(const FeedUpdate& upd) {
    auto book = upd.book();
    auto ts_bucket = ((book.Timestamp() - 1) / period_) * period_;
    if (last_sample_ts == ts_bucket) {
      *ts.rbegin() = book.Timestamp();
      for (int i = 0; i <= 2; i++) {
        *askp[i].rbegin() = book.AskN(i)->price;
        *askq[i].rbegin() = book.AskN(i)->qty;
        *bidp[i].rbegin() = book.BidN(i)->price;
        *bidq[i].rbegin() = book.BidN(i)->qty;
      }
    } else {
      last_sample_ts = ts_bucket;
      ts.push_back(book.Timestamp());
      for (int i = 0; i <= 2; i++) {
        askp[i].push_back(book.AskN(i)->price);
        askq[i].push_back(book.AskN(i)->qty);
        bidp[i].push_back(book.BidN(i)->price);
        bidq[i].push_back(book.BidN(i)->qty);
      }
      if (ts_bucket % 3'600'000'000'000) {
        printf("1 hour passed: %ld\n", ts_bucket);
      }
    }
  }

  int64_t last_sample_ts = 0;
  int64_t period_;
  std::vector<int64_t> ts;
  std::vector<double> askp[3];
  std::vector<double> bidp[3];
  std::vector<double> askq[3];
  std::vector<double> bidq[3];
};

int main() {
  auto start = TimestampFromDatetime(2019, 9, 1);
  auto end = TimestampFromDatetime(2019, 9, 7);

  Sampler sampler(start, end);
  FastFeedSubsystem fss(start, end, 10 * 1024 * 1024);
  //   auto p = OkexFuturesProduct::FromNativeStr("", start);
  auto p = HuobiFuturesProduct::FromNativeStr("BTC_CQ", start);
  fss.SubscribeProduct(&p, &sampler);
  fss.Run();

  return 0;
};
